#include <WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>
#include <time.h>
#include <WiFiUdp.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


// WiFi credentials
const char *ssid = "SZMINWIFI";        // Replace with your WiFi name
const char *password = "qwedcxza123";  // Replace with your WiFi password


// 定义GPS模块的串口连接引脚
// 修正引脚定义（ESP32-C3的硬件串口1）
#define GPS_RX_PIN 0  // ESP32的RX0接GPS模块的TX
#define GPS_TX_PIN 1  // ESP32的TX0接GPS模块的RX
// 改用硬件串口（删除SoftwareSerial）
HardwareSerial SerialGPS(1);  // 使用硬件串口1

// 在常量定义区添加LED引脚定义
#define LED_WIFI 12
#define LED_GPS 13

TinyGPSPlus gps;

// 在常量定义区添加OLED引脚定义
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// MQTT Broker settings
const int mqtt_port = 8883;                                      // MQTT port (TLS)
const char *mqtt_broker = "l1097b20.ala.cn-hangzhou.emqxsl.cn";  // EMQX broker endpoint
const char *mqtt_topic = "mm203";                                // MQTT topic
const char *mqtt_username = "esp";                               // MQTT username for authentication
const char *mqtt_password = "public";                            // MQTT password for authentication


// 控制继电器开关

#define KG1 18
#define KG2 19



// WiFi and MQTT client initialization
WiFiClientSecure esp_client;
PubSubClient mqtt_client(esp_client);



// Load DigiCert Global Root CA ca_cert, which is used by EMQX Platform Serverless Deployment

const char *ca_cert = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
)EOF";


// Function Declarations
void connectToWiFi();

void connectToMQTT();

void mqttCallback(char *topic, byte *payload, unsigned int length);


void setup() {
  Serial.begin(115200);

    // 初始化I2C
  Wire.begin(5, 4);  // SDA=5, SCL=4
  Wire.setClock(100000);  // 降低I2C时钟频率

  // 初始化OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306初始化失败"));
    for (;;);
  } else {
    Serial.println(F("SSD1306初始化成功"));
  }

  // 清除屏幕并设置默认显示参数
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  
 
  // 新增LED引脚初始化
  pinMode(LED_WIFI, OUTPUT);
  pinMode(LED_GPS, OUTPUT);
  digitalWrite(LED_WIFI, LOW);
  digitalWrite(LED_GPS, LOW);

  pinMode(KG1, OUTPUT);
  pinMode(KG2, OUTPUT);

  digitalWrite(KG1, HIGH);
  digitalWrite(KG2, HIGH);

  connectToWiFi();

  SerialGPS.begin(115200, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
  Serial.println("GPS Receiver Initialized");
  SerialGPS.setTimeout(10);  // 保持超时设置


  esp_client.setCACert(ca_cert);

  mqtt_client.setServer(mqtt_broker, mqtt_port);
  mqtt_client.setKeepAlive(60);
  mqtt_client.setCallback(mqttCallback);

  connectToMQTT();

  // 显示完成信息
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("System Ready");

  display.display();
  delay(1000);
}

// 添加显示函数
void displayStatus(String line1, String line2 = "", String line3 = "") {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println(line1);
  display.setCursor(0, 20);  // 第二行从第16像素开始
  display.println(line2);
  display.setCursor(0, 40);  // 第三行从第32像素开始
  display.println(line3);
  display.display();
}

// 修改connectToWiFi函数
void connectToWiFi() {
  WiFi.begin(ssid, password);
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Connecting WIFI...");

  display.display();
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  digitalWrite(LED_WIFI, HIGH);
  displayStatus("WiFi OK");
  delay(500);
  Serial.println("\nConnected to WiFi");
}

bool relayState = false;    // 默认继电器关闭
bool destoryState = false;  // 自毁开关关闭





// 修改connectToMQTT函数
void connectToMQTT() {

  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Connecting MQTT...");

  display.display();

  while (!mqtt_client.connected()) {
    String client_id = "esp32-client-" + String(WiFi.macAddress());
    Serial.printf("Connecting to MQTT Broker as %s...\n", client_id.c_str());
    if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
      Serial.println("Connected to MQTT broker");
      displayStatus("MQTT OK");
      delay(500);
      mqtt_client.subscribe(mqtt_topic);
      mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^");
    } else {
      Serial.print("Failed to connect to MQTT broker, rc=");
      Serial.print(mqtt_client.state());
      Serial.println(" Retrying in 5 seconds.");
      delay(5000);
    }
  }
}

void mqttCallback(char *topic, byte *payload, unsigned int length) {

  String message;
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  Serial.println(message);

  // 根据接收到的消息控制继电器
  if (message == "ON") {
    digitalWrite(KG1, LOW);
    relayState = true;  // 更新继电器状态
    Serial.println("打开电源");
  } else if (message == "OFF") {
    digitalWrite(KG1, HIGH);
    relayState = false;  // 更新继电器状态
    Serial.println("关闭电源");
  } else if (message == "DESTORY") {
    digitalWrite(KG2, LOW);
    destoryState = true;  // 更新继电器状态
    Serial.println("开启自毁");
  } else if (message == "DESTORYSTOP") {
    digitalWrite(KG2, HIGH);
    destoryState = false;  // 更新继电器状态
    Serial.println("关闭自毁");

  } else if (message == "status") {
    // 查询当前继电器状态并返回
    StaticJsonDocument<128> statusJson;
    statusJson["relayState"] = relayState ? "ON" : "OFF";
    statusJson["destoryState"] = destoryState ? "ON" : "OFF";

    String statusJsonString;
    serializeJson(statusJson, statusJsonString);  // 将JSON文档序列化为字符串

    mqtt_client.publish("status", statusJsonString.c_str());  // 发送JSON格式的状态
    Serial.print("Relay status sent: ");
    Serial.println(statusJsonString);
  }

  Serial.println("\n-----------------------");
}


void loop() {
  if (!mqtt_client.connected()) {
    connectToMQTT();
  }
  mqtt_client.loop();

  // 调整原始数据显示方式（确保显示完整NMEA语句）
  static String rawBuffer;
  while (SerialGPS.available() > 0) {
    char c = SerialGPS.read();
    gps.encode(c);

    // 构建完整NMEA语句
    if (c == '\n') {
      // Serial.print("[RAW] " + rawBuffer);
      rawBuffer = "";
    } else if (c != '\r') {
      rawBuffer += c;
    }
  }

  // 调整数据处理时机（添加延迟保证解析完成）
  static uint32_t last = 0;

  if (millis() - last >= 2000) {
    last = millis();

    // Serial.print("卫星数: ");
    // Serial.print(gps.satellites.value());

    if (gps.location.isValid()) {
      // 获取经纬度信息
      double latitude = gps.location.lat();
      double longitude = gps.location.lng();

      // 构建JSON格式字符串，保留全部精度
      StaticJsonDocument<256> jsonPayload;                        // 创建一个足够大的JSON文档
      jsonPayload["lat"] = latitude;                              // 添加纬度
      jsonPayload["lng"] = longitude;                             // 添加经度
      jsonPayload["relayState"] = relayState ? "ON" : "OFF";      // 添加继电器状态
      jsonPayload["destoryState"] = destoryState ? "ON" : "OFF";  // 添加自毁继电器状态

      String jsonString;
      serializeJson(jsonPayload, jsonString);  // 将JSON文档序列化为字符串

      // 发布到MQTT
      mqtt_client.publish(mqtt_topic, jsonString.c_str());

      // 串口输出调试信息
      // Serial.print("发送JSON数据: ");
      // Serial.println(jsonString);
      digitalWrite(LED_GPS, HIGH);  // GPS有效时点亮LED

    } else {
      // GPS无效时，发送继电器状态信息
      StaticJsonDocument<128> jsonPayload;                        // 创建一个足够大的JSON文档
      jsonPayload["relayState"] = relayState ? "ON" : "OFF";      // 添加继电器状态
      jsonPayload["destoryState"] = destoryState ? "ON" : "OFF";  // 添加自毁继电器状态
      jsonPayload["lat"] = 0;                                     // 添加纬度
      jsonPayload["lng"] = 0;                                     // 添加经度

      String jsonString;
      serializeJson(jsonPayload, jsonString);  // 将JSON文档序列化为字符串

      // 发布到MQTT
      mqtt_client.publish(mqtt_topic, jsonString.c_str());

      // 串口输出调试信息
      // Serial.print("发送JSON数据: ");
      // Serial.println(jsonString);
      digitalWrite(LED_GPS, LOW);  // GPS无效时熄灭LED
      // Serial.println("GPS信号无效");
    }

    // 显示主要状态信息
    // 显示详细状态信息
    display.clearDisplay();
    display.setCursor(0, 0);

    // 第一行：电源状态
    display.print("Power: ");
    display.println(relayState ? "ON" : "OFF");
    display.println();

    // 第二行：自毁状态
    display.print("Destory: ");
    display.println(destoryState ? "ON" : "OFF");
    display.println();

    // 第三行：GPS状态
    display.print("GPS: ");
    display.println(gps.location.isValid() ? "Valid" : "Invalid");
    display.println();




    // 第五行：纬度
    if (gps.location.isValid()) {
      display.print("Lat: ");
      display.println(gps.location.lat(), 6);
      display.println();
    }

    // 第六行：经度
    if (gps.location.isValid()) {
      display.print("Lng: ");
      display.println(gps.location.lng(), 6);
    }

    display.display();
  }
}